#encoding:utf-8

'''
data=2017/1/11 下午4:24
__author__='binpo',
author_email='binpocn@163.com',
'''
import tornado
try:
    from grapheneapi.grapheneclient import GrapheneClient
    from grapheneapi.grapheneapi import GrapheneAPI
    from grapheneexchange.exchange import GrapheneExchange
except:
    pass
from logs import LOG
log=LOG('wallet')
import json
import hmac
import hashlib
import base64
import datetime
import urllib
import timeit
import sys
stat_time = 0.0
from models import *
PAGE_SIZE = 100
from pagination.page import Paginator

def hmac_md5(key,args):
    myhmac = hmac.new(key,args, hashlib.md5)
    str_result = base64.b64encode(myhmac.digest())
    return str_result

TOKEN='Bk6Ia3D1E52RDF2PsBx2Li3ev27dVo'


from concurrent.futures import ThreadPoolExecutor
from functools import partial, wraps
EXECUTOR = ThreadPoolExecutor(max_workers=10)
def unblock(f):

    @tornado.web.asynchronous
    @wraps(f)
    def wrapper(*args, **kwargs):
        self = args[0]
        def callback(future):
            self.write(future.result())
            self.finish()
        EXECUTOR.submit(
            partial(f, *args, **kwargs)
        ).add_done_callback(
            lambda future: tornado.ioloop.IOLoop.instance().add_callback(
                partial(callback, future)))
    return wrapper


# class EdrCoinStockHandler(tornado.web.RequestHandler):
#
#     def get(self):



class Config():
    wallet_host = "localhost"
    wallet_port = 8089
    wallet_user = "e-chat"
    wallet_password = "aa6vuCw84BxQa3uT"
    witness_url = "ws://127.0.0.1:5909"
    witness_user = "e-chat"
    witness_password = "aa6vuCw84BxQa3uT"
    account = "e-chat"

class BaseHandler(tornado.web.RequestHandler):

    @property
    def get_client_ip(self):
        ip = self.request.headers.get("X-Client-Ip",'')
        if ip==None or ip=='':
            ip = self.request.headers.get("X-Real-IP",'')
        if ip==None or ip=='':
            ip = self.request.headers.get("X-Forwarded-For",None)
        if ip==None or ip=='':
            ip = self.request.remote_ip
        return ip.split(',')[0]

    def prepare(self):
        self.get_paras_dict()

    def on_finish(self):
        try:
            if database:
                database.close()

            global stat_time

            if not stat_time:
                stat_time = timeit.default_timer()
            response_time = (timeit.default_timer() - stat_time) % 1000


            print ('---------------------------RT---------------------------------')
            print ('-> Current url   : ', self.request.uri)
            print ('-> Response time : ', response_time, ' s')
            print ('-> Request method: ', self.request.method)
            print ('--------------------------------------------------------------')

        except Exception as e:
             pass

    def get_paras_dict(self):
        """
        :todo 获取请求参数 字典
        """
        if self.request.method == 'GET':
            query = self.request.query
            self.qdict = urllib.parse.parse_qs(query)
            for k, v in self.qdict.items():
                self.qdict[k] = v and v[0] or ''
        elif self.request.method in ('POST', 'PUT', 'DELETE'):
            self.qdict = {}
            query = self.request.arguments
            for key in query.keys():
                self.qdict[key] = len(query[key]) != 1 and query[key] or (query[key][0] and query[key][0] or '')

    def get_page_data(self,query,page_size=PAGE_SIZE):

        if self.get_argument("page_size",''):
            page_size = int(self.get_argument("page_size",PAGE_SIZE))
        page = int(self.get_argument("page", 1))
        offset = (page - 1) * page_size
        result = query.limit(page_size).offset(offset)
        page_data = Paginator(self.get_page_url, page, query.count(), page_size)
        page_data.result = result
        return page_data

    def get_page_url(self, page, form_id=None):
        """参数解析
        :page 页号
        :form_id
        """
        if form_id:
            return "javascript:goto_page('%s',%s);" % (form_id.strip(), page)
        path = self.request.path
        qdict = {}
        if self.request.method == 'GET':
            query = self.request.query
            # qdict =
            for k, v in urllib.parse.parse_qs(query).items():
                if isinstance(v, list):
                    qdict[k] = v and v[0] or ''
                else:
                    self.qdict[k] = v and v[0] or ''
        else:
            qdict = {}
            query = self.request.arguments
            for key in query.keys():
                # # if isinstance(query[key], list):
                # #     qdict[key] = query[key] and query[key] or ''
                # # else:
                # print type(query[key])
                # print len(query[key])
                # print len(query[key])
                if isinstance(query[key], list):
                    if len(query[key]) == 1:
                        qdict[key] = query[key][0]
                    else:
                        qdict[key] = query[key]
                else:
                    qdict[key] = query[key]
                # qdict[key]=len(query[key])==1 and query[key][0] or query[key]
                # print qdict[key]
        qdict['page'] = page
        # print qdict
        return path + '?' + urllib.parse.urlencode(qdict)


def transfer_edc(to_account,ammount):

    # class Config():
    #     wallet_host = "localhost"
    #     wallet_port = 8089
    #     witness_url = "ws://127.0.0.1:5909"

    graphene = GrapheneClient(Config)
    graphene.rpc.unlock('aa6vuCw84BxQa3uT')
    data = graphene.rpc.transfer2('e-chat', to_account, ammount, "EDC", "", True)
    return data
    #graphene.rpc.transfer2('e-chat', 'binpocn163.com', '0.005', "EDC", "memo", True)

class TransferListHandler(BaseHandler):

    #@tornado.web.authenticated
    def get(self):
        self.qdict.get('status')
        query = Transfer.select()
        data = self.get_page_data(query)
        page_html = data.render()
        self.render('list.html',data=data,page_html = page_html )

class ExchangeListHandler(BaseHandler):

    #@tornado.web.authenticated
    def get(self):
        self.qdict.get('status')
        query = Exchange.select()
        data = self.get_page_data(query)
        page_html = data.render()
        self.render('exchange.html',data=data,page_html = page_html )

class LoginHandler(BaseHandler):

    def get(self):
        pass

from utils import get_current_price,get_usd_cyh
class ExchangeConvertHandler(BaseHandler):
    def get(self):
        try:
            price = get_current_price()
            chy = float(get_usd_cyh())
            # print type(chy), chy
            # print price * float(chy)
            #
            # 1000 = (x * price) * chy
            amount = self.qdict.get('amount','')
            try:
                amount = float(amount)              
                amount = amount/(price* chy)
                self.write(json.dumps({'status': 'success', 'amount': round(amount,3), 'info': '调用成功'}))
            except:
                log.error()
                self.write(json.dumps({'status':'fail','amount':'','info':'params error'}))
        except Exception as e:
            log.error()
            t,v,tb = sys.exc_info()
            self.write(json.dumps({'status': 'fail', 'amount': '', 'info':'params error'}))

class TransferHandler(BaseHandler):

    def check_xsrf_cookie(self):
        pass

    '''
    @unblock
    def get(self):
        data = self.request.body
        data = data.decode(encoding='UTF-8')
        params = json.loads(data)
        to_account = params.get('to_account','').strip()
        amount = params.get('amount','').strip()
        token = params.get('token', '').strip()
        if not to_account or not amount or not token:
            return json.dumps({'stat':500,'info':'参数错误'})
        try:
            float(amount)
        except:
            log.error()
            return json.dumps({'stat': 500, 'info': '参数错误'})

        dt = datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%dT%H:%M')
        args = ''.join([to_account,amount,dt])
        md5_token = hmac_md5(TOKEN.encode(encoding='UTF-8'),args.encode(encoding='UTF-8'))
        md5_token = md5_token.decode(encoding='UTF-8')
        transfer = Transfer()
        transfer.request_ip = self.get_client_ip
        transfer.amount = amount
        transfer.edc_account = to_account
        transfer.pub_date = datetime.datetime.now()
        transfer_id = transfer.save()
        if md5_token==token:
            try:
                dex = GrapheneExchange(Config)
                balances = dex.returnBalances()
                edc_coin = balances.get('EDC')
                if float(amount)>edc_coin:
                    return json.dumps({'stat': 400, 'info': 'Wallet EDC is not enough','session':''})
                else:
                    data = transfer_edc(to_account,amount)
                    session = data and data[0]
                    transfer.status = 1
                    transfer.content = json.dumps(data)
                    transfer.save()
                    return json.dumps({'stat': 200, 'info': 'success','session':session})
            except:
                log.error()
                return json.dumps({'stat': 400, 'info': '提现失败,账户错误或者其他原因','session':''})
        else:
            return json.dumps({'stat':500,'info':'token error','session':''})
    '''

    @unblock
    def post(self):
        try:
            data = self.request.body
            data = data.decode(encoding='UTF-8')
            params = json.loads(data)
            to_account = params.get('to_account','').strip()
            amount = params.get('amount','').strip()
            token_ammount=amount
    
    
    
            token = params.get('token', '').strip()
            if not to_account or not amount or not token:
                return json.dumps({'stat':500,'info':'参数错误'})
    
            price = get_current_price()
            chy = float(get_usd_cyh())
            try:
                amount = float(amount)
            except:
                log.error()
                return json.dumps({'stat': 500, 'info': '参数错误'})
    
            amount = amount / (price * chy)
            amount = round(amount, 3)
    
            dt = datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%dT%H:%M')
            args = ''.join([to_account,token_ammount,dt])
            md5_token = hmac_md5(TOKEN.encode(encoding='UTF-8'),args.encode(encoding='UTF-8'))
            md5_token = md5_token.decode(encoding='UTF-8')
            transfer = Transfer()
            transfer.request_ip = self.get_client_ip
            transfer.amount = amount
            transfer.edc_account = to_account
            transfer.pub_date = datetime.datetime.now()
            transfer_id = transfer.save()
    
            if md5_token==token:
                try:
                    dex = GrapheneExchange(Config)
                    balances = dex.returnBalances()
                    edc_coin = balances.get('EDC')
    
                    if float(amount)>edc_coin:
                        return json.dumps({'stat': 400, 'info': 'Wallet EDC is not enough','session':''})
                    else:
    
                        data = transfer_edc(to_account,str(amount))
                        session = data and data[0]
                        transfer.status = 1
                        transfer.content = json.dumps(data)
                        transfer.save()
                        # Transfer.update(status=3, content=json.dumps(data)).where(Transfer.id==transfer_id).execute()
                        return json.dumps({'stat': 200, 'info': 'success','session':session})
                except:
                    log.error()
                    return json.dumps({'stat': 400, 'info':"Error connecting to Client!",'session':''})
            else:
                return json.dumps({'stat':500,'info':'token error','session':''})
        except:
            t,v,tb = sys.exc_info()
#             traceback.print_tb(tb)
            return json.dumps({'stat':500,'info':v,'session':''})
    
